/**
 * @class ErrorLog 错误日志模型
 */
const BaseMod = require('./base');
const Platform = require('./platform');
const Channel = require('./channel');
const { DateTime, UniCrypto } = require('../lib');
module.exports = class ErrorLog extends BaseMod {
    constructor() {
        super();
        this.tableName = 'error-logs';
    }

    /**
     * 错误日志数据填充
     * @param {Object} reportParams 上报参数
     */
    async fill(reportParams) {
        let params, errorHash, errorCount, cacheKey;
        const fillParams = [];
        const platform = new Platform();
        const dateTime = new DateTime();
        const uniCrypto = new UniCrypto();
        const channel = new Channel();
        const { needCheck, checkTime } = this.getConfig('errorCheck');
        const errorCheckTime = Math.max(checkTime, 1);
        let spaceId;
        let spaceProvider;
        for (const rk in reportParams) {
            params = reportParams[rk];
            errorHash = uniCrypto.md5(params.em);
            cacheKey = 'error-count-' + errorHash;
            // 校验在指定时间段内是否已存在相同的错误项
            if (needCheck) {
                errorCount = await this.getCache(cacheKey);
                if (!errorCount) {
                    errorCount = await this.getCollection(this.tableName)
                        .where({
                            error_hash: errorHash,
                            create_time: {
                                $gte: dateTime.getTime() - errorCheckTime * 60000,
                            },
                        })
                        .count();
                    if (errorCount && errorCount.total > 0) {
                        await this.setCache(cacheKey, errorCount, errorCheckTime * 60);
                    }
                }

                if (errorCount && errorCount.total > 0) {
                    if (this.debug) {
                        console.log('This error have already existsed: ' + params.em);
                    }
                    continue;
                }
            }

            //获取云端信息
            spaceId = null;
            spaceProvider = null;
            if (params.spi) {
                //云函数调用参数
                spaceId = params.spi.spaceId;
                spaceProvider = params.spi.provider;
            } else {
                //云对象调用参数
                if (params.spid) {
                    spaceId = params.spid;
                }
                if (params.sppd) {
                    spaceProvider = params.sppd;
                }
            }

            // 填充数据
            fillParams.push({
                appid: params.ak,
                version: params.v ? params.v : '',
                platform: platform.getPlatformCode(params.ut, params.p),
                channel: channel.getChannelCode(params),
                device_id: params.did,
                uid: params.uid ? params.uid : '',
                os: params.on ? params.on : platform.getOsName(params.p),
                ua: params.ua ? params.ua : '',
                page_url: params.url ? params.url : '',
                space_id: spaceId ? spaceId : '',
                space_provider: spaceProvider ? spaceProvider : '',
                platform_version: params.mpv ? params.mpv : '',
                error_msg: params.em ? params.em : '',
                error_hash: errorHash,
                create_time: dateTime.getTime(),
            });
        }

        if (fillParams.length === 0) {
            return {
                code: 200,
                msg: 'Invild param',
            };
        }

        const res = await this.insert(this.tableName, fillParams);
        if (res && res.inserted) {
            return {
                code: 0,
                msg: 'success',
            };
        } else {
            return {
                code: 500,
                msg: 'Filled error',
            };
        }
    }

    /**
     * 错误日志清理
     * @param {Number} days 日志保留天数
     */
    async clean(days) {
        days = Math.max(parseInt(days), 1);
        console.log('clean error logs - day:', days);

        const dateTime = new DateTime();

        const res = await this.delete(this.tableName, {
            create_time: {
                $lt: dateTime.getTimeBySetDays(0 - days),
            },
        });

        if (!res.code) {
            console.log('clean error log:', res);
        }
        return res;
    }
};
